/*
 * ============================================================================
 *
 *       Filename:  protoMsg.h
 *
 *    Description:  header file for gpbMessage
 *
 *        Version:  1.0
 *        Created:  08/27/11 11:22:58
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author: Chengxin Cai 
 *        Company: Hewlett-Packard Development Company, L.P. 
 *
 * ============================================================================
 */

#ifndef __PROTO_MSG_H
#define __PROTO_MSG_H

#include <string>
#include <vector>
#include <list>

#include <boost/any.hpp>

#include <google/protobuf/compiler/importer.h>
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>

const int  SP_PROTO_IMPORT_FAIL                   = 113003500,
        SP_PROTO_MSG_NOT_INIT                  = 113003501,
        SP_PROTO_INVALID_FIELDNAME             = 113003502,
        SP_PROTO_INVALID_FIELDINDEX            = 113003503,
        SP_PROTO_INVALID_FIELDTYPE             = 113003504,
        SP_PROTO_REQUIRED_FIELD_EMPTY          = 113003505,
        SP_PROTO_INVALID_REPEATED_NUMBER       = 113003506;

class GpbMessage // class to handle google protocol buffer message
{

   public:
      GpbMessage(google::protobuf::compiler::MultiFileErrorCollector 
                 *errorCollector = NULL);
      ~GpbMessage();

      int import(const std::string &, const std::string &, 
                                      const std::string &);

      //\! brief get field value from a message
      //\! return boost::any, if fails any is empty (check any.empty())
      boost::any getFieldValue(const std::string &) ;

      std::vector<boost::any> getFieldValues(const std::string &) ;

      //\! brief get field type from a message
      //\! return the message_type of a field if the field is valid
      std::string getFieldType(const std::string &) ;

      //\! brief set field value from a message,
      //\! return 0 if the operation is correct, or error code
      int setFieldValue(const std::string &, const std::string &);

      int addFieldValues(const std::string &, const std::vector<std::string> &);

      //\! brief update timestamps
      //\! return 0 if the operation is correct, or error code
      int updateTimestamp(const std::string &, const std::string &, const std::string & pnm = "");

      //\! brief get the human readable string, never fail
      std::string getDebugString() const;

      //\! brief get the compact string 
      //\! return if fail, return an empty string
      std::string getDataString() const;

      //\! brief fill the message
      //\! return 0 if the operation succeed, or error code
      int fill(const std::string &);

      //\! brief fill the message
      //\! return 0 if the operation succeed, or error code
      int fill(std::list<std::string> &, int);

      //\! brief return information if the above operations failed
      std::string getFieldName() const { return fieldName_; }

      //\! brief return the debug string of message_
      std::string DebugString() const { return message_->DebugString(); }
   private:
      google::protobuf::compiler::MultiFileErrorCollector *errorCollector_;
      google::protobuf::compiler::DiskSourceTree sourceTree_;
      google::protobuf::compiler::Importer importer_;
      google::protobuf::DynamicMessageFactory messageFactory_;

      google::protobuf::Message *message_;

      std::string fieldName_;
};
#endif
